Repository navigation
Release v1.1.0 - Design, memory and native Mission scheduling - #1395
pascalandr wants to merge 159 commits into
Conversation
…1194) ## Summary - New **Support CodeNomad** help page (10 languages): what sponsorship pays for, the funding policy (a contribution, not a purchase; never required to download, use or update) and one button per funding channel naming who receives the money. - **Download page** ends with a short *Support development* section with the same buttons; the help **header** gains a *Sponsor* link; the former support page is retitled **Bug reports and source builds** (ids unchanged) so the two are not confused. - **App**: *Support CodeNomad* in Settings → Info (secondary button between Updates and Diagnostics), in the Help menu after *CodeNomad Help* (Electron and Tauri, English help-page fallback) and as a palette command without a default shortcut. All open the localized help page. - **Repository**: `.github/FUNDING.yml` lists the maintainer's GitHub Sponsors profile and the Support page (the Sponsor button needs *Settings → General → Features → Sponsorships*). Channels live in `docs/help/funding.json` and render through a `{{funding}}` directive allowed only on the download and sponsor pages, so adding a channel needs no retranslation. Entries are validated (exact keys, unique ids, `https://github.com/sponsors/<login>` only) and escaped; a page using `{{funding}}` with no channel fails the build. CSP unchanged. Agreed with the co-maintainer before publishing. ## Validation - `npm run test:help`: 31/31 (27 pages × 10 locales, funding validation and placement). - `node scripts/test-help-browser.mjs`: 47/47 (header overflow at 390 px in en/he/ne/ja/zh-Hans, button geometry). - `npm run typecheck`; unit tests help-url, hotkey-bindings, menu-labels; browser tests help-command, server-info, view-menu-electron (22/22); `cargo test` for the Tauri crate (291/291, including the English sponsor fallback). - Independent review: zero findings.
… the last clone's location (#1195) The clone dialog fills Destination folder as the repository's `git clone` folder name (HTTPS, scp-style and local sources, including `/.git` sources) inside a parent: the folder chosen with Browse, which now picks the folder that will contain the clone; else the folder above the last successful clone; else the folder above the most recent project. A typed destination is kept and sent unchanged, so the clone's folder can be renamed by hand; its parent is what the next clone remembers. The picker opens on the parent of the current destination. Drive, filesystem and UNC share roots keep their trailing separator, and `#` stays part of local paths. The parent is remembered per window at once and saved in the server-scoped `ui` state (`lastCloneParent`) for other windows and restarts; saves are chained so the last clone's parent is kept, and the chain is tracked by `storage.trackWrite` so native shutdown waits for queued saves. The picker description, the Projects help in all ten locales and dev-docs/PROJECTS.md are updated. clone-destination.test.ts and preferences-clone-parent.test.ts (added to CI) and a new launcher browser test cover suggestions, Browse, typed paths, pending saves and the shutdown drain.
…instead of a broken icon (#1196) ## Problem Agents often answer with a Markdown image of a file on their machine, e.g. after OpenCode's `image_generate` tool: ```markdown  ``` The renderer cannot load a local path (`C:` is read as a URL scheme), so the transcript showed a broken-image icon, even though the same image was already displayed a few rows above by the `read` tool that loaded that file. ## Change - `lib/markdown.ts`: a Markdown image whose source is a local path (`C:/…`, `C:\…`, `file://`, absolute or relative POSIX paths) renders as its alt text (or the file name) in a `span.markdown-local-image`, never as a broken `<img>`. Remote, `data:` and other URL sources keep marked's default rendering. - `components/markdown.tsx` + new `lib/markdown-local-images.ts`: blocks containing such a label look up a completed tool image of the same path among the session's loaded messages (the image's file name, or its single-image tool's `filePath`; Windows paths compare case-insensitively; a relative path must match exactly one known path's end) and swap the label for an `<img>` with that image's existing source (`data:` URI or CodeNomad's session-media path). The lookup tracks the store, so an image arriving after the answer resolves it in place. Blocks without a local image never read the session's parts. - No new backend route: nothing outside the transcript's own images is ever loaded. An unmatched path keeps its alt text. - `dev-docs/TRANSCRIPT.md` documents the rule; styles in `styles/markdown.css`. ## Validation - Unit (`markdown-local-images.test.ts`): path recognition (Windows, UNC-free drive paths, `file://`, POSIX, relative, schemes left alone), matching rules, candidate collection from completed tool parts (running and unsafe images ignored), and rendering (alt text, file-name fallback, remote images unchanged, hostile alt/path text escaped). Existing `markdown.test.ts` passes. - Browser (`tool-images.test.ts`, real `Markdown` component, store and history load): an answer without the read result shows alt text and no `<img>`; once the read tool's image of that path is loaded, the same answer shows the decoded image while an unknown path keeps its alt text; no overflow at 380 px. The other five image tests still pass. - `npm run typecheck --workspace @codenomad/ui`.
The automation-forms test where an agent fills the real Mission editor failed intermittently at its Create step since the project nesting depth editor joined the creation Options. Opening Options starts a depth read that showed a "Saving..." status, then swapped it for the result; each swap pushed the footer down about 100 ms later, so native automation measured Create, the layout moved and the click landed on the footer, and nothing was submitted. The status also claimed a save during a read. The depth editor now shows its busy status only while confirming or saving; a read keeps the field read-only without announcing anything. In the panel, the creation form fills the height below the header and its footer sticks to the panel's bottom edge, so Create keeps its place while depth reads, catalogs or alerts resize the body. automation-forms answers the depth read like a native runtime and waits for the effective depth before clicking Create, as an agent would, and mission-control checks that a read only locks the field while a write announces Saving. The target test passed 8/8 including a cold first run (the old test failed 3/8 on dev), Create stayed in place across read timings and panel sizes, and every Missions, editor, preferences and drawer browser suite and the UI typecheck pass.
## Summary - `CODE_OF_CONDUCT.md`: Contributor Covenant 2.1; reports go privately to a maintainer. - `GOVERNANCE.md`: maintainers and roles, decisions (significant ones need both maintainers), joining and leaving, current funding channel, no self-approved expenses from shared funds, succession. - `SECURITY.md`: supported versions, private reporting through GitHub with a maintainer-contact fallback, what to include. - `CONTRIBUTING.md` links both. Private vulnerability reporting must be enabled by a repository admin (Settings, Security) for the main reporting route. ## Validation Links and facts checked; independent review: zero findings.
… help (#1198) The **Image generation** info tip (Settings → Providers → Images) and the help's Images section said agents ask for permission before each image. OpenCode's default agents allow `image_generate` without asking (the Build agent's rules start with `* → allow`), so the promise was inaccurate; whether an agent asks is governed by the user's own OpenCode permissions, as for any tool. The tip now reads "Each image is a paid request." and the help keeps the background-job and saved-file behavior, in all ten locales. Copy-only change: help checks and UI typecheck pass.
…ges help (#1199) The **Image generation** info tip (Settings → Providers → Images) kept the sentence "Each image is a paid request." after #1198. It is inaccurate too: image models can be free or local. The tip now reads "Lets agents create and edit images with an image model from a connected provider. Applies to every project." and the help's Images section says each image is generated in the background and saved as a file, in all ten locales. Help checks and UI typecheck pass.
…own experimental block (#1200) ## Problem OpenCode reads `experimental.media_blob` from the whole `experimental` object of the highest-priority configuration document that has one (upstream: anomalyco/opencode#60410). A project `.opencode/opencode.jsonc` holding only `{"experimental":{"subagent_depth":8}}` — exactly what the Missions depth editor writes — turned **Store images once** off in that project even though the Global box was checked. Settings only showed a caption ("Another OpenCode configuration's experimental settings take precedence here: images stay inside each message."). ## Change - **Images** (`opencode/image-settings.ts`): when the selected Location's own project document (the project write target) decides `media_blob` through its existing `experimental` object, the snapshot reports `mediaStorage.project`, the box shows the effective value with no caption, and saving writes `media_blob` to the Global document **and** to that project block. A block that disappeared after reading is never recreated (conflict). Image generation is read per field and still writes Global only. The caption remains for deciding documents CodeNomad does not edit. - **Subagent depth Inherit** (`opencode/subagent-depth-settings.ts`): removes, in one comment-preserving edit, a project `experimental` object left empty or holding only a `media_blob` equal to the value removal exposes. That value counts only when certain (runtime declares `media_blob`; the next native object belongs to the Global write target and deep-equals its fresh document); otherwise the object stays, which hides nothing new. `removeEmptyNativeObject` takes a removability predicate; `samePath`/`maskedBy` move to `opencode/experimental-layers.ts`. - The depth editor writes only the depth. Predicting the inherited object for a newly created project block needs OpenCode's full layer order (explicit, managed, content, normalization, watcher lag) and stays out of scope; the root cause is upstream (#60410), and Images now shows and fixes the per-project value in one click. - Docs: `dev-docs/SETTINGS.md`, `dev-docs/MISSIONS.md`, help `providers.md` and `missions.md` in 10 locales. ## Validation - `image-settings.test.ts`, `subagent-depth-settings.test.ts` (6/6): project write, comment preservation, disappeared-block refusal, Inherit cleanup with BOM/CRLF comments, kept block for lagging/normalized entries, no Global object, missing capability - `websearch-settings.test.ts` browser test (4/4); the new Images assertion fails without the card change - `scripts/test-subagent-depth-settings-native.mjs` (Global image storage cleanup) and `scripts/test-image-settings-native.mjs --expect-supported` against an isolated OpenCode 2.2.1 CLI - `scripts/test-help.mjs` (31/31), server and UI typecheck, `git diff --check`
…ent (#1201) Slice 2 ("content") of the Design image companion (SCR v1.3.1 §5, §11.2, §15; AC-14, AC-15, AC-49 content part). ## What - Native OpenCode files under `packages/server/src/opencode/design/opencode/`: the `design` primary agent and seven unlisted skills (`design-core` + six recipes), with per-file licence notices, `NOTICE.md` and the Apache-2.0 licence. They work unchanged when copied into a project's or the global `.opencode/`. - `design/content.ts`: `loadDesignContent()` (text embedded through a `.md` loader added to the shared native plugin build) and strict `parseDesignContent()` for checkout code and tests. - Nothing registers or displays the content yet: the activation slice wires it into the session-pruning plugin. ## Attribution - `design-logo` ← brandkit (MIT); `design-ui-mockup` ← imagegen-frontend-web/mobile (MIT); full MIT notices kept in the files. - `design-core` and the agent ← Open Design's review ideas, the five directions (rewritten, no brand names) and the image-poster prompt order (Apache-2.0, marked as modified work). - Other recipes written for CodeNomad. No CC-BY prompts, no design systems. ## Tests - `node --import tsx --test packages/server/src/opencode/design/content.test.ts` (9/9; verified against 19 content mutations) - `node --test packages/server/scripts/native-plugin-build.test.mjs` (2/2, self-contained bundle outside the checkout) - `node --import tsx scripts/test-design-content-native.mjs <cli>` against OpenCode 2.2.1 and 2.1.2 (added to the PR build); outside CI it requires `CODENOMAD_NATIVE_FIXTURE_PARENT` outside the user's home because project discovery walks every ancestor - Server typecheck; `build:pruning`, `build:automation`, `build:missions`
…iven by backend leases (#1202) Slice 1 ("activation-agent") of the Design image companion (SCR v1.3.1 §11, decisions T1/T3/T6/T8; AC-1 to AC-7, AC-57, AC-49 installed-bundle part). ## What - **Backend request in leases** (`opencode/design/activation.ts`, `demand.ts`, `desktop-plugin-installation.ts`, `desktop-plugin-lifecycle.ts`): every retained session-pruning lease carries `{"version":1,"design":true}` while an installed, enabled panel extension declares `opencode.designAgent`; atomic rewrites only on change, serialized with the heartbeat; new installations start from the current state. Nothing can declare the permission until extension API 4 (slice 5), so Design stays inactive in production for now. - **Load-time registration** (`opencode/design/register.ts`, `session-pruning/desktop-plugin.ts`): agent and skill transforms registered once while the plugin loads, before `followPresence`; reconciliation flips a Location-local flag and reloads only on an actual change of the union of live requesters. User's own `design` / `design-*` win; their permissions apply; content (`loadDesignContent()` from #1201) loads lazily. Capability-gated on agent/skill transforms. - **Shared observation** (`desktop-plugin-presence.ts`): v3 per-process snapshot with bounded (256 B) lease reads; `observeDesignRequest`. - **Status** (`opencode/design/status.ts`): `designAgentStatus` → `present` (content version) / `user` / `absent` from `GET /api/agent`. - Docs: `dev-docs/OPENCODE_COMPATIBILITY.md`, `dev-docs/SESSION_PRUNING_RPC.md`. ## Tests - Unit: `node --import tsx --test packages/server/src/opencode/design/*.test.ts packages/server/src/opencode/session-pruning/*.test.ts packages/server/src/opencode/desktop-plugin*.test.ts` - Native (PR build): `node scripts/test-design-activation-native.mjs <cli>` after `npm run build:pruning`, against isolated OpenCode 2.2.1 and 2.1.2 with fake chat/image models (outside CI with `CODENOMAD_NATIVE_FIXTURE_PARENT` outside the home). 2.2.1: activation ≈1.9 s, one ask under Design and Build, late Location < 1 s, single-requester expiry ≈16 s, disable ≈2 s, replaced shim/bundle keeps priority and permissions. - Server typecheck; `packages/server/src/index.ts` ≈789 lines (+5).
…sion-pruning plugin (#1203) Slice 3 ("history-gallery") of the Design image companion (SCR v1.3.1 §10; AC-17..AC-21, AC-23, AC-50, AC-51, AC-56, server part of AC-9/AC-10; AC-22 except the full-size `not-previewable` decode bound, which belongs to the API 4 channel in slice 5 per §10.1). ## What Four fixed session-pruning RPCs (documented in `dev-docs/SESSION_PRUNING_RPC.md`): - `images`: bounded pages of the conversation's image `read` parts (pixels targets) and `image_generate` calls (native states); prompt/model/parent only when proven by the execution-interval rule, else "unverifiable" with pixels; prompts only for a marked root on host request. - `imageRead`: bytes of a read image part only; reuses the asset reader, split into `storedAsset` / `assetBytes` (`assetRead` unchanged). - `imageReference`: prefill target validation with the post-write check, including a parallel generation to the same file still without a notice. - `imagesConversation`: authoritative lookup of the Location's root, unarchived, marked conversation (incomplete search → unknown), open/create under a process lock, new on request. ## Notes - Cursor binding includes an `"images"` label so an `assets` cursor cannot be replayed. - `imageCount` / `lastUsed` are composed by the host in slice 5. - Consumed native contracts: the `Saved image: … (` notice text and tool `metadata.path` / `jobID` / `model`; a change degrades to unknown/unverifiable. ## Tests - `node --import tsx --test packages/server/src/opencode/session-pruning/*.test.ts packages/server/src/server/routes/session-pruning.test.ts packages/server/src/server/__tests__/instance-proxy.test.ts packages/server/src/server/routes/panel-extension-assets.test.ts` (297/297): 30 ported prototype mutations on two real 2.2.1 transcripts with/without media_blob; 9 reintroduced regressions detected. - `node scripts/test-session-pruning-native.mjs <cli>` (isolated 2.2.1): Images conversation lookup/open/new, found again after a daemon restart. - Design tests, server typecheck, `build:pruning`. - `scripts/test-session-pruning-native.mjs` ≈453 lines.
…nd exclude its images from Git (#1204) Slice 4 ("conversation-ui") of the Design image companion (SCR v1.3.1 §7.3, §7.4, §12, T8; AC-8, AC-11, AC-12, AC-13). ## What - **Route** `POST /api/workspaces/:id/images-conversation` (lookup / open / new) over the session-pruning `imagesConversation` RPC, with Location ownership, the worktree deletion fence and `blocked: unavailable` for older plugins. - **Git exclusion** of `.codenomad/design/` through the execution host's Git (WSL distro Git for WSL Locations), reporting `excluded` / `not-repository` / `unavailable`; the shared helper now appends instead of rewriting, preserving foreign bytes; `.gitignore` never touched. - **UI** `resolveImagesConversation` + `showImagesConversation`: localized title "Images", `agent: "design"` only when present, CodeNomad-resolved model at creation, found conversation keeps its model, composer focused, nothing sent. - **Composer**: "The Design agent is not available" + "Use the default agent", blocking send only when the selected agent is `design` and missing (T8). 10 locales. - Docs: `dev-docs/COMPOSER.md`, `dev-docs/SESSION_PRUNING_RPC.md`. ## Help Nothing in this slice is reachable without the Design panel (API 4 / extension slices), so `docs/help` is unchanged here; the Design help section lands with the panel. ## Tests - Server: `design-git-exclude`, `images-conversation` route, `git-process`, `worktree-inventory`, `native-worktree-custody`, `session-pruning`, `assets-conversation` (38/38, including a real WSL Ubuntu project and linked worktree with `CODENOMAD_TEST_WSL_DISTRO=Ubuntu`). - Browser: `images-conversation` (3/3) plus composer/session regressions (`composer-alternate-send`, `composer-draft-safety`, `composer-resume-typing`, `session-fork`, `session-create-feedback`, `interruption-dock`). - UI and server typecheck; `node scripts/test-help.mjs`. - Long files touched: `prompt-input.tsx` ≈1041, `http-server.ts` ≈2488, `api-client.ts` ≈857, `session-view.tsx` ≈726.
…anion (#1205) Slice 5 ("api4") of the Design image companion (SCR v1.3.1 §9, T2, T5, T7; AC-24..AC-33, AC-42, AC-53; plus items deferred by slices 1–4: `opencode.designAgent` permission, full-size decode bound, `imageCount`/`lastUsed`, host deadline). ## What - **API 4 schema** (`panel-extensions/contract.ts`, `archive.ts`): `session.context` + `session.images.read`, `session.images.prompts` (requires read), `images.conversation`, `composer.prefill`, `panel.preferences`, `opencode.designAgent`. APIs 1–3 unchanged. - **Install sentences** before the trust checkbox (10 locales). - **Fixed routes** (`server/routes/panel-extension-api4.ts`) with permission checks before and after reads; 19 s server stop, 8 s per daemon call, aborted with the frame. - **Channels** (`ui/.../api4-channel.ts`): 19.5 s deadline, 4 requests per mount, late results dropped, coalesced invalidations, full-size `not-previewable` bound. - **`conversation.status()`** read-only (exclusion checked as Git reads lines; `imageCount` exact or `null`); open/startNew append. - **Prefill** (`composer-prefill.ts`): composer rules on the resulting draft, `{{n}}` references revalidated and cited as text, never sends, 1/s. - **Preferences**: 4 KiB JSON per extension in the existing store; corrupt store → unavailable, untouched. - Docs: `PANEL_EXTENSIONS.md#api-4`, `COMPOSER.md`; help `extensions.md` in 10 locales. The panel-side "Design agent missing" warning is rendered by the Design extension (host exposes `designAgent`). ## Tests - Server: 83 passed (+ real WSL Ubuntu exclusion check with `CODENOMAD_TEST_WSL_DISTRO=Ubuntu`). - Browser: `panel-extension-api4` 10, `panel-extensions` 14, `images-conversation` 4, composer 12. - UI unit 7; UI and server typecheck; help 31/31. - Long files touched: `prompt-input.tsx` ≈948, `http-server.ts` ≈2300 (one line each).
Slice 8 (part a) of the Design image companion (SCR v1.3.1 §18; AC-45, AC-47). - `docs/help/<10 locales>/extensions.md#design` (+ `#design-conversation`, `#design-light-table`, `#design-without-codenomad`), using the merged UI labels and the extension's labels. - One link sentence at the end of `providers.md#images`; existing Images texts unchanged; no new permission/consent wording. - `dev-docs/PANEL_EXTENSIONS.md` and `dev-docs/OPENCODE_COMPATIBILITY.md` touch-ups; COMPOSER, SESSION_PRUNING_RPC and AGENTS already describe the delivered state. **Merge timing:** the help says to install Design from the catalogue, so this merges together with the catalogue publication. Checks: `node scripts/test-help.mjs` (31/31), `node scripts/build-help.mjs` (27 pages × 10 languages), `node scripts/test-help-browser.mjs` (47/47).
…andbox on native hosts (#1208) Slice 6 (qa-native) of the Design image companion (SCR v1.3.1; AC-16, AC-41, AC-52, AC-54). Test code only; no product source changes. - `scripts/test-design-companion-native.mjs`: isolated OpenCode daemon, scripted chat model, fake image model; AC-16 and native AC-52 (re-read 35 assistant messages later). Added to the PR build on Windows/Ubuntu/macOS. - `--ui <Design ZIP>` → `scripts/test-design-companion-ui.mjs` + `fixtures/design-companion.tsx`: real UI S8 path with the installed extension and real-transcript Markdown rendering (AC-52, AC-54). - `scripts/panel-extension-native-probe.mjs`, `test-panel-extension-native.mjs --api4` (also off Windows), new `test-panel-extension-electron.mjs`: sandbox invariants with negative controls (AC-41). - `fixture-exemptions.ts`: registers the Images conversation and API 4 browser tests required by `fixture-wiring`. Runs: Windows (OpenCode 2.2.1 native + UI path; WebView2 and Electron runners), Ubuntu VM (WebKitGTK and Electron runners). **Not run:** macOS WKWebView — the VM stops at its login screen.
…ct (#1209) ## Summary - OpenCode **2.2.3** becomes both the **technical minimum** and the **recommended** runtime. The minimum moves because upstream [#60258](anomalyco/opencode#60258) (shipped in 2.2.2) changed the image tool contract that CodeNomad's Images gallery, Design agent and Images settings consume: one name, `experimental_image_generate`, for the tool, its permission action, its job type and its completion notices' `metadata.source`, and the tool on by default (only `experimental.image_generate: false` disables it). On 2.2.2+, the gallery lost every generation entry and the Design companion fixture timed out; 2.2.1 passed. - Images are implemented for the 2.2.3 contract only, with no fallback to the old name: `IMAGE_TOOL` drives the gallery and its proof; `imageGenerationSelection` reads unset as on; the Design agent and skills name the new tool; the activation fixture exercises the image tool instead of falling back to webfetch; the gallery fixture represents the 2.2.3 transcript format. - Older daemons (2.1.x, 2.2.1, 2.2.2) go through the existing below-minimum path (`native_contract`). The 2.1.0 client/plugin/schema pins stay. - Help (all ten locales), READMEs, `CONTRIBUTING.md`, `dev-docs` (compatibility, pruning, panel extensions, settings) and the architecture skill describe the new minimum, its reason and default-on image generation. The setup minimum-reason UI string is updated in all locales. ## Contract review (v2.2.1 → v2.2.2 → v2.2.3; 40 + 101 commits) Reviewed from the exact tags `v2.2.1` (`3ebcf9a32c`), `v2.2.2` (`098aa7fd6e`) and `v2.2.3` (`082ac6281f`), the published npm packages, and an authenticated OpenAPI dump from each official CLI running in its own sandbox. The [changelog](https://opencode.ai/changelog) has entries for both 2.2.2 (29 October, highlights only) and 2.2.3 (30 October, full notes); everything below was also checked against the commit log and source. **Headline:** the HTTP contract CodeNomad consumes didn't change, but 2.2.2 **renamed the image tool** from `image_generate` to `experimental_image_generate` and **turned it on by default** ([#60258](anomalyco/opencode#60258)). CodeNomad's Images/Design features match the old name and the old default, so they break on 2.2.2 and later (see [Design companion finding](#design-companion-finding)). Nothing else found affects CodeNomad. - **Authenticated OpenAPI:** **134 paths and 162 operations** on all three, the same operation set. Schemas 355 → 350 → 351. - **Added/removed operations:** none in either release. - **Changed operations (2.2.2):** `GET /api/model`, `GET /api/event`, `PUT /api/pty/{ptyID}`, `POST /api/shell`, `GET /api/shell/{id}/output`, `POST /api/debug/heap-dump` and `GET /api/experimental/migration/v1`. All of these are **representation-only**: the Effect 4.0.6 JSON Schema output flattens nested `anyOf`, bounds integers with `maximum: 9007199254740991` (and `minimum` for signed integers), and rewrites the numeric-string query pattern. The event-type and model-type enums are unchanged. - **Changed operations (2.2.3):** only the description of `POST /api/credential`, which can now be refused by an `integration.connect` policy. - **Consumed schemas:** the same family selector as the 2.2.1 review (`V2EventEncoded`, `Session.*`, `SessionStats.*`, `Form.*`, `Permission.*`, `Prompt*`, `Event.*`, `Location.*`, PTY/Shell). Re-derived from that description it selects 104 schemas at 2.2.1 (the 2.2.1 file says 103), all byte-identical from 2.1.4 to 2.2.1. - In 2.2.2 the seven alias copies `Form.Fields_1..3` and `Session.Message.Native_1..4` collapse into their base schemas, which are byte-identical to the copies, leaving **97**. Of these, 71 are byte-identical and 24 differ only in generator representation. - Two changes are additive and optional: `Session.Info.time.busy`, the start of the latest execution ([#59910](anomalyco/opencode#59910)), and the input field `PromptInput.FileAttachment.source` (`Prompt.FileSource`, inline or uri; CodeNomad doesn't send it). - `V2EventEncoded`, `Session.Message.*` content, `Session.Inbox.*`, `Form.*` semantics, `Permission.*` and `Event.SeqEncoded` are unchanged. - From 2.2.2 to 2.2.3 the family is byte-identical. - **`Config.InfoEncoded`:** no semantic change in 2.2.2 (representation only). 2.2.3 extends the managed-policy `action` enum (top-level and `experimental.policies`) with `integration.connect`, `mcp.use`, `skill.use` and `plugin.use` ([#60315](anomalyco/opencode#60315)); CodeNomad writes no policies. The *meaning* of `experimental.image_generate` changed: unset now means on, and only `false` turns it off. The schema shape stayed the same and the OpenAPI carries no description, so no contract signal reveals it. - **Schedules (not consumed on dev):** `when` becomes optional; `if`/`until` conditions (shell in 2.2.2, Code Mode in 2.2.3) are added; outcomes gain `checked`/`expired`. - **Admission:** every predicate in `compatibility/negotiate.ts` (unchanged since the 2.2.1 review) holds on 2.2.1, 2.2.2 and 2.2.3. - **Instance proxy:** no new routes and an unchanged allowlist. Proxied routes whose representation changed: `GET /api/model`, `PUT /api/pty/{id}`, `POST /api/shell` and `GET /api/shell/{id}/output`. Integer bounds and an equivalent numeric pattern accept everything CodeNomad sends. - **Published declarations** (2.2.1 → 2.2.3): - **Client:** 185 methods on all three; the method tree is identical. 2.2.2 adds the generated types `ScheduleCondition*`; `FormFields2` is renamed to `FormFields1`, which is generated-type churn. 2.2.3 adds the Promise media helpers `withMediaRefs`, `mediaHashFromUri` and `MediaRequestOptions` ([#60116](anomalyco/opencode#60116)) and persistent-PTY frame helpers in `solid/pty`. CodeNomad imports none of these. - **Schema:** 2.2.2 adds schedule conditions (`ShellCondition`, `CheckMode`, …) and exports `SessionLegacy.part`. 2.2.3 adds `CodeCondition*` and `policy.Action`. - **Plugin:** 2.2.2 adds the GUI `ComposerQuoteAnchor`/`ComposerFocusOptions`. 2.2.3 has no export changes, but the optional peers `@opentui/*` become `>=0.8.0` ([#60385](anomalyco/opencode#60385)). The published `dependencies.effect` moves from **4.0.1 to 4.0.6** (2.2.2). - **Typecheck:** the server and UI typecheck with **0 errors** against the 2.2.2 and 2.2.3 client/schema/plugin/effect declarations through scratch `paths` overrides. The pinned 2.1.0 control is also clean. The harness now also remaps `effect` itself; the 2.2.1 harness skipped it because effect's `exports` are plain `.js` strings. - **Host modules:** the three daemon-loaded bundles still import `@opencode/plugin` (`Plugin`), `/effect` (`Plugin`, `Rpc`, `Location`), `/promise/adapter` (`fromPromise`), `/rpc` (`Rpc`), `effect` and `effect/encoding` (`Base64Url`) from the host. A probe plugin in an isolated **2.2.3** daemon resolves every module and binding, as on 2.2.1. `runtime-modules.ts` is unchanged between the tags. - **Host Effect: 4.0.1 → 4.0.6** (2.2.2, [#59630](anomalyco/opencode#59630)). The 2.1.0 `@opencode/schema`/`@opencode/client` code bundled into the Missions and pruning plugins now runs on host Effect 4.0.6. The plugin-runtime, pruning, Missions-contract, permission-receipts and image-settings native suites pass on 2.2.3. - **Private native services:** the keys (`LocationServiceMap`, `Form`, `Permission`, `Location`, `Job`, `Database`, `Session`, `Bus`) and the members CodeNomad calls are unchanged. The changes are additive: `Permission.Unattended` (a reference that denies unanswerable asks for schedule checks), a `CorrectedError.message` getter, and `Session` deciding fork media from the parent's location. - **Storage** (three migrations): `session_part` (new table), `session_v2.time_busy` and four `schedule` check columns. - **`session_part`** ([#58915](anomalyco/opencode#58915)): history reads now *prefer* `session_part` rows over `session_message.data.content` for assistant messages. The projector writes parts there only for messages that already have part rows, so new messages stay inline. Every 2.2.3 fixture DB inspected has **0** `session_part` rows, and upstream `dev` (`1e28374e48`, 30 October) has no writer either. - The tables CodeNomad reads directly keep their shape. - **Forward risk:** when a release starts writing parts, CodeNomad's direct `session_message.data.content` readers and the pruning `UPDATE … json_set(data,'$.content',…)` (`session-pruning/transaction.ts`) would silently miss or be shadowed by part rows. See Recommendations. - **Behavior changes checked:** - **Image generation** (2.2.2): renamed and on by default. See the [dedicated section](#design-companion-finding). - **Code Mode:** inner tool progress no longer replaces the `execute` call rows ([#60480](anomalyco/opencode#60480)), and progress is throttled to at most one update per 100 ms ([#60120](anomalyco/opencode#60120)). Programs see the same failure text as direct calls ([#60109](anomalyco/opencode#60109)), `fetch` in Code Mode is now subject to `webfetch` permissions ([#59954](anomalyco/opencode#59954)), `for…in` visits inherited keys ([#59933](anomalyco/opencode#59933)) and `null` survives text encoding ([#57639](anomalyco/opencode#57639)). The run-to-completion regression behind the 2.1.2 minimum passes on 2.2.3: `{ total: 2000, beforeAwait: 1000, count: 1000 }`. - **Permissions and MCP:** permission reasons and feedback are kept in MCP tool failures ([#60102](anomalyco/opencode#60102)). Shell permission checks moved fully off tree-sitter and now check redirects, PowerShell method calls and dynamic directory changes ([#60332](anomalyco/opencode#60332), [#60376](anomalyco/opencode#60376)), so some shell commands may now ask where they didn't. The managed-policy split (`integration.use` vs `mcp.use`/`skill.use`/`plugin.use`) is a changelog "breaking change" for managed deployments only. - **Sessions:** deleting a session removes its persistent terminals ([#60322](anomalyco/opencode#60322)), and a persistent terminal with a missing cwd is rejected ([#60300](anomalyco/opencode#60300)). Forked and imported sessions store media as blobs when `media_blob` is on ([#60118](anomalyco/opencode#60118)). The native fork suite passes on 2.2.3. - **Providers:** a built-in **Claude Agent** provider uses the user's Claude Code login ([#58782](anomalyco/opencode#58782)). Plugin-supplied model variants are preserved ([#60097](anomalyco/opencode#60097)), and the dynamic provider npm fallback runs after external SDK hooks ([#60380](anomalyco/opencode#60380)). These are source-reviewed and touch no consumed contract. - **Persistent PTY binary** (the process daemon): 2.2.2 switches from `@opencode-ai/pty` 0.3.1 to `@opencode/pty` **0.3.3** ([#60276](anomalyco/opencode#60276)). `process-daemon-v0.3.3` contains only the release commit after 0.3.2 (a version bump of the `@opencode/pty-*` binaries). **v0.4.0** (terminal renaming, [#60324](anomalyco/opencode#60324)) is **not** shipped in CLI 2.2.3, which pins 0.3.3. CodeNomad only lists persistent PTYs (worktree deletion guard), whose schema is unchanged apart from representation. - **Client fix not inherited:** the 2.2.3 client evicts missing sessions on 404 ([#60459](anomalyco/opencode#60459)). CodeNomad stays on the 2.1.0 client. - **`@opencode/ai` breaking changes** (media moved to `/experimental`, one `tool()`): CodeNomad doesn't import `@opencode/ai`. - Desktop/TUI-only changes (timeline performance, side-panel tabs, spellcheck, question sounds, OpenTUI 0.8) don't affect CodeNomad. **Verdict:** - The **2.1.0 client/plugin pins stay**. Bumping them would bring nothing CodeNomad consumes. - No consumed HTTP/plugin contract broke; the breaking change is the image tool contract of #60258, consumed by the Images gallery, the Design agent and the Images settings. - **Decision applied in this PR:** 2.2.3 becomes both the minimum and the recommendation, and Images are implemented for the 2.2.3 contract only (see Summary). This replaces the review's initial suggestion to keep the 2.1.2 minimum and accept both tool names. **Not verified here:** - the full native suite matrix on 2.2.2/2.2.3; only the runs in Appendix I were performed; - the forward-compatibility of the `session_part` readers against a runtime that writes parts (no such runtime exists yet); - the Claude Agent provider and shell-permission changes at runtime (source only); - macOS/Linux. --- ## Design companion finding **Symptom:** `scripts/test-design-companion-native.mjs <cli>` passes on 2.2.1 and fails on 2.2.2 and 2.2.3 with `Error: Timed out: series 1 generated and read`. Reproduced independently in a scratch checkout of `origin/dev` (`f39642bc4`), with `CODENOMAD_NATIVE_FIXTURE_PARENT` outside the home: ``` test-design-companion-native 2.2.1 exit=0 PASS AC-16, AC-52 test-design-companion-native 2.2.2 exit=1 Timed out: series 1 generated and read test-design-companion-native 2.2.3 exit=1 Timed out: series 1 generated and read ``` **What the step waits for** (`test-design-companion-native.mjs:238-241`): the fixture's loopback chat provider answers a `RUN [...]` turn with two tool calls `{ tool: "image_generate", args: { prompt, path: ".codenomad/design/icon/<name>" } }`. The step then waits until the transcript holds two synthetic notices with `metadata.source === "image_generate"` (line 209) and two `read` parts of the generated files. No HTTP generate route, file watch or media blob is involved; it is the agent tool path. **Cause: an intentional upstream contract change, not an upstream bug.** In 2.2.2, [#60258](anomalyco/opencode#60258) (`d4e48f54da`, "turn experimental_image_generate on by default") changed `packages/core/src/tool/plugin/image-generate.ts`: - `export const name = "image_generate"` → `"experimental_image_generate"`. That one constant is the tool name, the permission action (`assertions: ["experimental_image_generate", "edit", "read"]`), the Job `type`, and the completion notice's `metadata.source`. `session/execution/restart.ts` also tags restart-recovery notices `source: "experimental_image_generate"`. - The opt-in became default-on: `if (!enabled || imageGenerate(entries) === false) return`. An unset `experimental.image_generate` now offers the tool; only `false` removes it ("still honored for configs from when the tool was opt-in; permissions are the supported way to turn it off"). - The 2.2.2 changelog states it: "agents can now use `experimental_image_generate` without additional configuration". 2.2.2 also wraps the notice text as `<image id="…" state="…">\n…\n</image>` and adds `id` to the tool output ([#60098](anomalyco/opencode#60098)). CodeNomad's `Saved image: (.+) \(` parse still matches; `jobID`, `state` and `path` metadata are unchanged. **Evidence** (fixture DBs copied read-only to `evidence/`): ``` 2.2.3, original fixture (calls "image_generate"): seq 5 tool image_generate error "No tool named \"image_generate\" is currently available. Please use a tool from the available tool list." (x2) -> no image job, no notice, no read: the wait times out. 2.2.3, fixture with the tool name changed (scratch copy; CodeNomad server code unmodified): seq 5 tool experimental_image_generate completed {path:…/icon-minimal-a, model:"fiximg/image", jobID:"image_18cfb59…"} seq 18 synthetic {"source":"experimental_image_generate","jobID":"image_18cfb59…","state":"completed",…} <image id="image_18cfb59…" state="completed"> | Image request finished. Saved image: … seq 20 tool read completed (x2) … seq 40/48/49 refinement -> files, image calls and reads all correct, then AssertionError: generations.length 0 !== 3 (test line 260: gallery "generation" entries) ``` So the product bug is real and independent of the fixture: on 2.2.2+ CodeNomad's Images gallery finds **no generation entries**. Images still appear through their `read` parts, but without prompt, model, lineage or "proven" origin, and `galleryImageReference` refuses them as `changed`. **CodeNomad code that assumes the 2.2.1 name or default** (origin/dev): | Where | Assumption | Effect on 2.2.2+ | | --- | --- | --- | | `session-pruning/assets-gallery.ts:56,139` | `part.name === "image_generate"` | no generation entries; references refused `changed` | | `session-pruning/assets-gallery-proof.ts:104,130` | tool name and notice `source === "image_generate"` | no calls or notices, so no provenance proof | | `opencode/image-settings.ts` `imageGenerationSelection(undefined) → false` (doc: "Reads … as OpenCode does") | unset means off | Settings → Images shows **Off** and `images.status()` returns `"disabled"` while the tool is offered; help step "Turn on image generation" (`docs/help/en/extensions.md:73`) is no longer needed | | `opencode/design/opencode/agents/design.md`, `skills/design-core`, `design-logo`, `design-ui-mockup` | the agent is told to call `image_generate` | the model sees only `experimental_image_generate`; the first call can fail with "No tool named …" | | `scripts/test-design-companion-native.mjs:125,209,238,301` | fixture calls/filters `image_generate` | red on 2.2.2+ | | `scripts/test-design-activation-native.mjs:76,307` | ask rule on action `image_generate`; tool detection by that name | **passes but loses coverage**: `askTool` falls back to `webfetch` on 2.2.2/2.2.3 (logged) | | `dev-docs/SESSION_PRUNING_RPC.md`, `PANEL_EXTENSIONS.md`, `SETTINGS.md` | describe `image_generate` parts and opt-in | out of date for 2.2.2+ | User permission rules written for action `image_generate` no longer match on 2.2.2+; that is an OpenCode-side change for users. CodeNomad's help never names the permission action; the Design fixtures and agent use `experimental_image_generate`. **Fix in this PR** (2.2.3 contract only, no fallback): 1. One `IMAGE_TOOL = "experimental_image_generate"` constant drives the gallery and its proof; the gallery reads the 2.2.3 notice format. 2. The native fixtures use the new tool; the activation fixture exercises it (default on) instead of falling back to webfetch. 3. The Design agent and skills name `experimental_image_generate`. 4. `imageGenerationSelection` reads an unset `experimental.image_generate` as on; only `false` disables it. Settings → Images and `images.status()` report it that way. ## Follow-up - Hardening for `session_part` (independent of this upgrade, no 2.2.3 regression): make the direct readers and the pruning transaction fail safe when `session_part` has rows for the target messages. ## Isolated Windows qualification Base: dev `f39642bc4`; Node 25.2.1 (local; CI runs the pinned 24.20.0); exact official CLI **2.2.3**; locked client/plugin **2.1.0**; `CODENOMAD_NATIVE_FIXTURE_PARENT` outside the user profile for the Design fixtures. - **Before the image fix (recommendation-only change):** every native suite passed on 2.2.3 except the Design companion end to end, which passes on 2.2.1 and times out on 2.2.2/2.2.3 at "series 1 generated and read" (`No tool named "image_generate" is currently available`). - **After this change, on 2.2.3:** Design companion (3 files, 2 series, all proven, lineage), Design activation (image tool offered to Design and Build, default on), Design content, image settings (default on, Off→On hot reload), session pruning including session images/media, Code Mode jobs `{ total: 2000, beforeAwait: 1000, count: 1000 }`. - **Full native set on 2.2.3 (before the image fix, unaffected areas):** plugin runtime, automation, Location/worktrees/event relay, permission receipts, Git init/degraded, Missions (contract, family control, native, trajectory) and all 11 recurring journeys, sessions (environment, fork, aside, interrupt, lifecycle, blank cleanup, compaction, prompt skills, providers, service usage, web search, plugin packages, output limit, Promise-tool failure, subagent depth, temporary workspaces), migrations from 2.1.2/2.2.1/2.2.2, install/upgrade/legacy replacement. - **Units and checks after the change:** root and server typecheck clean; server **2,825 passed, 9 skipped, 1 cancelled** (`index.test.ts` shutdown test timed out under full-suite load; **4/4** alone); gallery 107/107; Design 23/23; opencode-update 62 passed / 1 skipped; touched UI units 8/8; browser `opencode-setup` + `websearch-settings` 38/38; native plugin build 2/2; ten-locale help 31/31.
…er the same name (#1210) A failed image generation (here three Gemini calls rejected with 'API key not valid') followed by a retry under the same file names made every retried image 'origin not verifiable' in the Design light table, and the retry's generation showed 'No read-back image attached': the proof saw two possible writers of each file. OpenCode 2.2.3 publishes a job's notice only after `jobs.wait` (`image-generate.ts` `notifyWhenDone`), and a failed or cancelled job saves nothing afterwards. `proveWriter` now leaves out a call whose single decoded notice (per `generationState`) reports `error` or `cancelled` before the remaining writer's start. Notified after the retry started, never notified, or notified twice → still unverifiable. - `assets-gallery-proof.ts` (+10/−1), `assets-gallery-bounds.test.ts` (5 cases × plain/blob; positives red without the change), `dev-docs/SESSION_PRUNING_RPC.md`. - Checks: session-pruning, session-pruning route and API 4 tests; server typecheck.
Help tables broke words in the middle of narrow columns ("Compone nt", "CodeNom ad project tab" in Missions → Lifetime and service restarts). Cells used `overflow-wrap: anywhere`, which also lowers each cell's minimum width to one character, so the automatic table layout squeezed short label columns in favor of long description columns.
Cells now use `overflow-wrap: break-word`: an over-long word still wraps, but column widths are computed from whole words. Inline code keeps `overflow-wrap: anywhere`, and wide tables keep scrolling locally.
test-help-browser.mjs checks, in every English article at 390 and 1440 px, that no word outside code spans two lines in a table cell; it fails with the previous rule and the help browser suite passes (47/47). Review checked all ten locales at both widths.
… login (#1214) Usage showed nothing for OpenCode's `claude-agent` provider (Claude Agent SDK), which signs in with Claude Code's own login (`claude auth login`): CodeNomad had no usage reader for that ID. `claude-agent` is now an alias of the existing `claude-code` reader, which reads Claude Code's login on the daemon host; both IDs share one cached reading and backoff, and the login never appears in responses or logs. Without a Claude Code login it shows not configured, with no fallback to another provider's credential. PROVIDER_ACCOUNTS.md, the server README and the providers help page (ten locales) are updated. Validation: service and route tests cover both IDs and fail without the alias; usage, route and credential tests (29/29), root typecheck and the help checks pass.
) The Mission editor's Playbook selector showed only names; what each playbook does was documented only in the help. The selected playbook's one-sentence description now appears directly under the selector (referenced by its aria-describedby) and follows the selection. Five `missions.control.template.<id>.description` strings reuse each locale's help wording in all ten locales; the paragraph takes the editor's existing secondary text style. The Missions help (ten locales) and dev-docs/MISSIONS.md mention it. Validation: a browser test opens the real editor, checks the default description, its placement and fit, then Exploration and Compare two models; it fails without the component change. A unit test checks every locale has its own description for each playbook. Mission editor and automation browser tests (98/98), UI unit tests, help checks and the root typecheck pass.
A user asked whether sessions and sub-agents in a mission can use earlier sub-agent sessions and mission context. The Missions help now explains how context flows: the mission map as shared, durable memory; what the coordinator, native-subagent tasks, independent-session tasks and their helpers each receive; how results come back; how later tasks build on earlier ones (dependencies, reused conversations, existing independent conversations) and what compaction means for model context versus stored history; daily runs and follow-up missions; and on-demand search of earlier conversations through CodeNomad's session search tool. The section (`#context-flow`, `#context-search`) is in all ten locales with each locale's UI labels; every statement is mapped to the code in the PR description. Validation: help structure and browser checks pass (31/31, 47/47); two review rounds, the second with no findings.
…t now (#1219) A user reported that pausing a mission stopped it abruptly, mid-step; pausing by hand ("pause this session" queued to the coordinator and sub-agent) let the current step finish and resumed cleanly. Pause interrupted the whole native family at once. Pause from the panel is now graceful (`graceful: true`): it records a paused control with no targets and no native side effect, so it settles at once. The paused context every actor reads at each model request asks it to finish only the step in progress, start no new work or sub-agents and end its turn; the plugin's context hook adds it for native descendants, walking ordinary sub-agents' ancestry (bounded, cached parent IDs) to their actor and re-reading a paused chain so only sessions still placed with the actor's admitted project and Location receive it. Dispatch blocking and report parking apply at once, as before. While the activity projection observes a running, queued, background, Form or permission actor of a gracefully paused mission, the panel shows "Pausing: the steps in progress are finishing." and Interrupt now, which sends the existing immediate Pause (family interruption and receipts unchanged). An immediate Pause is valid from paused only after a graceful one. Play after a graceful Pause tells the coordinator that delegated work may have stopped early and should be continued, not restarted. The flag is carried by the route, RPC schema, plugin, journal (graceful means no targets), projection and UI intents; requests without it keep the immediate behavior. MISSIONS.md, the Missions help (ten locales) and three UI strings (ten locales) are updated. Tests cover the lifecycle transitions and replay, the journal rule, the real plugin context hook for the coordinator and three levels of sub-agents (including moved sessions and warm caches), and the real panel for running and Form-waiting work. Three review rounds; the last had no findings.
…th their names (#1218) The Model selectors of mission profiles (Settings → Missions defaults, Mission editor Options, Compare Model A/B) listed every catalog model as raw `provider/id`, unfiltered. They now show the same list and names as the conversation's model selector. The composer's catalog building moves unchanged into `lib/model-catalog.ts` (`buildProviderCatalog`, `listCatalogModels`), and preference filtering into `stores/model-picker.ts` (`preferredModelList`): hidden models are left out, favorites-only applies while a favorite remains, and models sort by provider then name. Mission controls reuse them, keep only tool-capable models, and group options by provider. Summaries show friendly names without their own catalog read (`knownModelName`), with names keyed by the workspace-root Location and connection generation so a fresher conversation catalog wins. A saved value the list leaves out stays selected under its name, or as "· Unavailable" when the selector cannot offer it; stored values keep the `providerID/id` format. A global `optgroup` rule styles provider groups in native selects. Help (ten locales) and MISSIONS.md describe the list. Tests cover the shared helpers, freshness and Location fences, and the real Settings, editor and Compare selectors, including hidden, favorite-filtered, unknown and tool-less saved values; three review rounds, the last with no findings. Rebased on #1219: typecheck, help checks and 77 mission/model browser tests pass.
Setting many rows of the same kind (Message content eyes, session
selection checkboxes, model visibility) took one click per row. Image
editors let users drag across a column of layer eyes instead; CodeNomad
now does the same.
Pressing a toggle and dragging out of it flips it, and every toggle of
the same column or list the pointer then crosses takes that new state;
toggles already in that state stay as they are. Releasing the button
clicks nothing, including the first toggle when the drag returns to it.
It works for mouse and pen; touch drags keep scrolling, and a touch
landing during a mouse drag leaves the sweep going.
Implementation: `lib/toggle-sweep.ts` installs one capture listener on
first use. Toggles opt in with `data-toggle-sweep={toggleSweepGroup(...)}`,
one group per column or list, so the Message content eyes and chevrons
sweep separately and exclusive selectors (tabs, presets) never sweep.
Each toggle changes through its own click, so its handlers, disabled
state and accessibility are unchanged; state is read from `checked`
(labels stand for their checkbox) or `aria-pressed`/`aria-checked`. The
drag is sampled every 4 px so fast moves skip no row, text selection
and native drag are blocked during a sweep, the trailing click is
swallowed, and a sweep whose release went elsewhere ends at the next
move without the button. `afterSweep` defers costly work until the
sweep ends.
Groups: Message content visibility and expansion columns, session
selection checkboxes, right-panel customization (built-in tabs and
Status sections; extension activation is a trust decision and stays
out), notification routing, model visibility, and the multi-select
options of agent forms and provider sign-in forms.
Message content dropped clicks made while a save was pending and showed
a row only once the server confirmed it, re-rendering the transcript
for each. Rows now show their requested state at once; a sweep saves
once, on release, so the transcript re-renders once. Saves run in
order and each batch of rows is sealed as it joins the queue, so a
later click never jumps ahead of a preset change nor rides along with a
sweep still held.
Notification routing shows each box at once, writes the whole table
once per sweep, runs its writes one after another so an older table
never lands last, and asks for System permission once per gesture.
Model visibility already showed pending changes and wrote them in
order.
Validation: browser regressions in transcript-presets (a single jump
across four eyes with slow saves, shown during the drag with nothing
saved, then one write on release; a hidden row that stays hidden; a
release back on the origin; the chevron column alone; a held sweep not
persisted by queued saves; a row clicked after a preset applying after
it), session-search (both directions, a release over a row title
opening no session, a lost release leaving no sweep, a touch mid-drag)
and notification-routing (one write per sweep, serialized writes with
the last winning, one permission request). Each fails with its part of
the fix removed. Two gatekeeper rounds ended with no P0-P2 finding; the
user validated the behaviour in a separate Electron dev instance.
dev-docs/UI_CONVENTIONS.md and dev-docs/TRANSCRIPT.md record the
convention, and the help describes the gesture in all ten languages.
Follow-up to #1183, which merged with the sticky creation footer. That footer's second review left two P2s open: - **R3:** a stale-map or cleanup-unavailable banner rendered after the form moved Create by about 32 px during a native automation click. - **R4:** on short panels, the sticky footer covered the focused field or made Options unreachable. ## Change - **Layout:** while creating, the form fills the Missions panel as a column. Its **body is the only scroller**, and the footer sits below it, outside that scrollport, so native focus scrolling keeps the focused field visible. - **Banners** shown during creation are ordered above the form. They shrink the body and never move the footer; their text and roles are unchanged. - **Short panels** (the footer plus an 8rem body don't fit): the whole form scrolls in the panel, with the footer after it. This uses the existing short-layout helper, renamed `mission-panel-scroll.ts` and shared with the task tree, which re-reveals the focused element when the mode switches. - **Unaffected:** edit/delete forms and the Preferences depth editor. ## Validation - **automation-forms:** five held outcomes (three depth reads, a stale banner, cleanup unavailable) released during the real controller's click. Create's box is unchanged and exactly one POST is sent. - **mission-panel-host:** - A real-keyboard Tab pass at 1000x600 and 260x300, with Options and the brief prompt open, hit-tests every focused control. - At 220x120, Options opens and every control is reachable. - **Red checks:** the sticky CSS fails both banner cases (-32.5 px) and the focus checks; removing the fallback fails the short-panel checks. - **Passing on current dev:** UI typecheck; automation-forms (2 runs), mission-panel-host, mission-control, mission-panel-layout, mission-panel-geometry, mission-create-submit, mission-create-refusals, mission-editor-lifetime.
notification-routing.test.ts (#1221) serves the status-tokens fixture through startProductFixture like its sibling tests but was missing from the fixture exemption map, so fixture-wiring.test.ts failed browser shard 1. It now carries the same exemption. fixture-wiring.test.ts and notification-routing.test.ts pass locally (3/3).
## Summary - OpenCode **2.2.5** becomes the **recommended** (qualified) runtime. The **2.2.3 minimum** and the 2.1.0 `@opencode/client`/`plugin`/`schema` pins stay: neither 2.2.4 nor 2.2.5 changes a contract CodeNomad consumes. - `RECOMMENDED_OPENCODE_VERSION` is 2.2.5, and the reviewed-publication shortcut in `contractProfile` lists 2.2.3 and 2.2.5; other versions, 2.2.4 included, keep negotiating their authenticated schema. The CI `latest` lane already resolves the latest stable CLI. - Help (all ten locales), READMEs, `CONTRIBUTING.md`, `dev-docs/OPENCODE_COMPATIBILITY.md` and the architecture skill state two separate versions again: minimum 2.2.3 with its reason, recommendation 2.2.5. ## Contract review (v2.2.3 → v2.2.4 → v2.2.5; 31 + 19 commits) Reviewed from the exact tags `v2.2.3` (`082ac6281f`), `v2.2.4` (`45898d0f85`) and `v2.2.5` (`9bbb8ce18c`), the published npm packages, and an authenticated OpenAPI dump from each official CLI running in its own sandbox. The [changelog](https://opencode.ai/changelog) has full notes for 2.2.4 and 2.2.5 (both 30 October); everything below was also checked against the commit log and source. CodeNomad side: `origin/dev` `605820669`. **Headline:** neither release changes a contract CodeNomad consumes. 2.2.4 adds opt-in **artifacts** (seven `/api/experimental/artifacts` operations, four tools, a plugin hook), **renamable persistent terminals**, and moves background-job recovery markers from `kv` into a new **`job` table**. 2.2.5 is a bug-fix release; its one schema change is that `compaction.buffer` accepts a percentage such as `"20%"`. The image tool contract adopted in #1209 (`experimental_image_generate`, on by default) is unchanged through 2.2.5, and still nothing writes `session_part`. - **Authenticated OpenAPI:** 134 → **138** → 138 paths, 162 → **169** → 169 operations, schemas 351 → 362 → 363. - **Added operations (2.2.4):** `GET /api/experimental/artifacts/providers`, `GET|POST /api/experimental/artifacts`, `GET|PATCH|DELETE /api/experimental/artifacts/{artifactID}`, `GET /api/experimental/artifacts/{artifactID}/view/*` ([#60351](anomalyco/opencode#60351)). None removed in either release. - **Changed operations (2.2.4):** `GET /api/event`, where the `types` filter enum gains `persistent-pty.updated` and `artifact.updated` (94 → 96 types, none removed). `PUT /api/experimental/persistent-pty/{ptyID}` can also rename (`title`; `null` clears it), `size` becomes optional, and a 501 `PtyFeatureUnsupportedError` is returned while an older terminal service can't rename ([#60329](anomalyco/opencode#60329)). - **Changed operations (2.2.5):** none. - **Consumed schemas:** same family selector as the 2.2.3 review, 97 schemas at every version. - 2.2.3 → 2.2.4: 95 byte-identical. The two that change, `PersistentPty.Info` (+ `userTitle`, nullable, required) and `PersistentPty.UpdateInput` (`size` optional, + `title`), are both additive. - 2.2.4 → 2.2.5: all 97 byte-identical. - `V2EventEncoded`, `Session.*`, `Form.*`, `Permission.*`, `Prompt*`, `Event.*`, `Location.*`, PTY/Shell are byte-identical from 2.2.3 to 2.2.5. - **`Config.InfoEncoded`:** 2.2.4 adds `experimental.artifacts` (boolean, opt-in). 2.2.5 turns `compaction.buffer` into `Config.Compaction.Percent | integer` ([#60647](anomalyco/opencode#60647)). `experimental.image_generate`, `experimental.media_blob` and `experimental.schedules` are unchanged. - **Admission:** every predicate in `compatibility/negotiate.ts` (unchanged on origin/dev) holds on 2.2.3, 2.2.4 and 2.2.5. `contractProfile` lists only `2.2.3` as reviewed, so 2.2.4/2.2.5 are admitted through authenticated contract recognition. - **Instance proxy:** the allowlist is unchanged on origin/dev. No added or changed route is proxied: artifacts and persistent PTYs are outside it. The proxied `GET /api/config` returns the additive config fields above. - **Published declarations** (2.2.3 → 2.2.5): - **Client:** 185 → **192** → 192 methods. 2.2.4 adds `experimental.artifacts.{providers,list,create,get,update,delete,view}`, the artifact and `PersistentPtyUpdated` types, and `PtyFeatureUnsupportedError`. It removes `createPtyClient`/`PtyConnectInput` from `@opencode/client/solid/pty`, which CodeNomad doesn't import. 2.2.5 adds `ConfigCompactionPercent`. - **Schema:** 2.2.4 adds the `artifact` module and `PersistentPty.Updated`; 2.2.5 adds `config/compaction` `Percent`. - **Plugin:** 2.2.4 adds `effect/artifact` and `promise/artifact` and `ctx.experimental.artifact` (`transform`, `reload`). 2.2.5 has no export changes. - **Typecheck:** the server and UI typecheck with **0 errors** against the 2.2.4 and 2.2.5 client/schema/plugin/effect declarations. The pinned 2.1.0 control is also clean. - **Host modules:** the bundles' host imports are identical to the 2.2.3 review. A probe plugin in an isolated **2.2.4** and **2.2.5** daemon resolves every module and binding. `runtime-modules.ts` is unchanged from v2.2.3 to v2.2.5. - **Host Effect:** stays **4.0.6** (`bun.lock` sha512 identical; published `dependencies.effect` 4.0.6). - **Persistent PTY binary:** the 2.2.4 and 2.2.5 CLIs ship `@opencode/pty` **0.4.0** (string `opencode-pty 0.4.0` in the Windows binary; 2.2.3: `0.3.3`). `process-daemon-v0.4.0` adds only terminal renaming ([#60324](anomalyco/opencode#60324)): an additive `rename` request and `features: ["rename"]` with an unchanged `PROTOCOL_VERSION`. CodeNomad only lists persistent PTYs (worktree deletion guard) and reads `status`/`cwd`. - **Private native services:** the keys (`LocationServiceMap`, `Form`, `Permission`, `Location`, `Job`, `Database`, `Session`, `Bus`, `Shell`) and the members CodeNomad calls are unchanged. The changes are additive: `Job.cancelSession` (2.2.4), `Permission.allows` (2.2.5; never asks, used by `edit` to decide whether to quote file lines), and `Session.remove` now calls `jobs.cancelSession`. The Missions recurrence clock calls `Job.get/start/cancel`. Its Job metadata carries no `sessionID`, so deleting a session doesn't cancel it. - **Storage:** one migration, `20261030054400_job` (2.2.4, [#60491](anomalyco/opencode#60491)). It creates `job`, copies every `kv` row `job.background/%` into it and deletes those `kv` rows. 2.2.5 adds none. - CodeNomad reads only its own `kv` keys (Missions, pruning receipts and claims), never `job.background/*`. - Native migration 2.2.3 → 2.2.4 passes. Every 2.2.4/2.2.5 fixture DB inspected holds the `job` table, **0** `job.background/` rows and no leftover `schedule:leader` lease. - **`session_part`:** still **not written**. `history.ts`/`projector.ts` are unchanged from v2.2.3 to v2.2.5, the projector still only rewrites existing part rows, and every inspected 2.2.4/2.2.5 fixture DB has **0** rows. The forward risk from the 2.2.3 review stands (Recommendations). - **Behavior changes checked** (plain-language list in [What users will notice](#what-users-will-notice)): - **Image tool** (#1209 contract): `image-generate.ts` is unchanged from v2.2.3 to v2.2.5. 2.2.4 refactors restart recovery into one `restartMessage` but keeps `metadata.source: "experimental_image_generate"`, `jobID`, `state`, `path` and the `<image id state>` notice text. Design companion, activation, content and image settings pass natively on 2.2.4. - **Schedules** (2.2.4, [#60478](anomalyco/opencode#60478), then `da87c475a7`): the loop now runs in every server process, including `opencode serve`, and elects a leader through a `kv` lease `schedule:leader` (claimed at boot, released when there are no active schedules). Firing stays opt-in (`experimental.schedules === true`). CodeNomad uses neither OpenCode schedules nor that key; Missions recurrence uses its own storage and the Job service. - **Sessions:** deleting a session now cancels its running background jobs (shell, image, subagent) and drops their markers (2.2.4). That is the intended upstream cleanup; CodeNomad's session deletions (blank-session cleanup, temporary workspaces) get it automatically. - **Events:** `persistent-pty.updated` and `artifact.updated` reach CodeNomad's shared event relay. The relay routes generically (`instance-events.ts`), the 2.1.0 client's SSE reader doesn't validate types, and the UI handles neither type. The native relay suite passes on 2.2.4. - **Tools** (2.2.5): a model call to `bash` runs as `shell` with shell permissions, and the result carries a note ([#60687](anomalyco/opencode#60687)). CodeNomad already groups and renders `bash` and `shell` alike (`message-part-grouping.ts:48`, `tool-call/utils.ts`). `read`/`edit` failure texts are richer ([#60688](anomalyco/opencode#60688), [#60689](anomalyco/opencode#60689)). - **Compaction** (2.2.5): the prompt is capped at the context window when a catalog's input limit is larger ([#60660](anomalyco/opencode#60660)), and `compaction.buffer` may be `"N%"`. CodeNomad never reads or writes `compaction.buffer`. LiteLLM context errors now trigger compaction ([#60692](anomalyco/opencode#60692)). - **Reasoning replay** (2.2.5, [#60498](anomalyco/opencode#60498)): reasoning is no longer re-sent as plain text after a model switch, and interrupted or errored reasoning is dropped from the request. This changes provider requests only; stored transcripts and `Session.Message.*` are byte-identical. - **MCP** (2.2.5): stdio messages over 10 MiB no longer disconnect a server ([#60694](anomalyco/opencode#60694)), and an idle Location no longer restarts its MCP servers right after shutting down ([#60668](anomalyco/opencode#60668)). - **Providers:** a Console-supplied provider can now be overridden by user, project and remote config (2.2.4). The Claude Agent provider only replaces Claude Code's `/login` hint with `claude auth login` in its errors ([#60592](anomalyco/opencode#60592)); the guided setup ([#60603](anomalyco/opencode#60603)) is OpenCode Desktop only. The provider ID (`Provider.ID.claudeAgent`) and its use of Claude Code's own login are unchanged, so CodeNomad's `claude-agent` quota reader (#1214) is unaffected. - **Service lifecycle:** the CLI now adds `127.0.0.1,localhost,::1` to `NO_PROXY`/`no_proxy` for itself and its children ([#60441](anomalyco/opencode#60441)), so loopback traffic from daemon-hosted code, CodeNomad's plugins included, bypasses environment proxies. CodeNomad sets no proxy variables. - **Code Mode, Forms, permission prompts, media blobs:** no source changes from v2.2.3 to v2.2.5 (`packages/codemode` only bumps its version). The Code Mode run-to-completion regression passes on 2.2.4: `{ total: 2000, beforeAwait: 1000, count: 1000 }`. - **`@opencode/ai`:** one `ai` object for Promise and Effect ([#60516](anomalyco/opencode#60516); left out of the changelog by [#60631](anomalyco/opencode#60631)). CodeNomad doesn't import `@opencode/ai`. - Desktop/TUI-only changes (desktop terminals on persistent PTYs, base-branch and worktree shortcuts, quote sending, flat inputs, palette ordering) don't affect CodeNomad. One indirect effect follows. - **Worktree deletion:** OpenCode Desktop terminals now live as persistent PTYs that survive restarts ([#60346](anomalyco/opencode#60346)). CodeNomad's guard (`routes/worktrees.ts`, "Running persistent PTY blocks deletion: <id>") will therefore refuse more often for users who also open terminals in OpenCode Desktop. The behavior is correct, but the message names the PTY ID rather than the terminal's title. **Verdict:** - The **2.1.0 client/plugin pins can stay**. Bumping them would bring only artifacts, PTY renaming and a config type, none of which CodeNomad consumes. - The **2.2.3 minimum has no reason to move**. No consumed HTTP, plugin, private-service or storage contract broke in 2.2.4 or 2.2.5. - **Recommend 2.2.5.** It is admitted today through contract recognition. Recommending it is CodeNomad-side bookkeeping: `RECOMMENDED_OPENCODE_VERSION` (`runtime-support.ts`), the reviewed-version check in `contractProfile` (`compatibility/runtime.ts`), the version texts in docs and help, and CI's qualification target. This is subject to the full native suite on the exact 2.2.5 CLI, run separately. - **No CodeNomad bug found** in 2.2.3 → 2.2.5. Risks: the `session_part` forward risk (unchanged) and the more frequent worktree-deletion refusal (UX). **Not verified here:** - the full native suite on 2.2.5: only a host-module probe ran natively on 2.2.5, and everything else for 2.2.5 is source and OpenAPI review (Appendix I); - the 2.2.4 recurring Missions journey (`test-recurring-simple-native` ABCDGELFWQN), which was interrupted by a server restart; - the `kv` → `job` migration with a real pending background marker: only the empty case ran, and upstream `job.test.ts` covers the copy; - whether a `bash` call is stored as `bash` or `shell` (source suggests the model's name is kept; CodeNomad renders both); - artifacts, Claude Agent and MCP stdio framing at runtime (source only); - macOS/Linux. --- ## What users will notice **OpenCode 2.2.4** - **Persistent desktop terminals:** OpenCode Desktop terminals belong to the session, keep their scrollback across server restarts, stay in sync with the TUI and other windows, and can be renamed. Renamed terminals keep their names. - **Artifacts (opt-in):** with `"experimental": { "artifacts": true }`, agents can publish, update and serve HTML or static artifacts (`artifact_create`, `artifact_read`, `artifact_update`, `artifact_delete`) through a built-in local provider, which stores files under OpenCode's data folder, or a plugin-provided one. - **Schedules:** enabled schedules also fire under `opencode serve`, and only once when several OpenCode processes share a database. They stay off unless `experimental.schedules` is `true`. - **Claude Agent:** OpenCode Desktop guides installation, `claude auth login` and connection checking. Error messages now say `claude auth login` instead of `/login`. - **Config:** user, project and remote configuration can override Console-supplied provider names, limits, variants, settings and headers. - **Networking:** requests to the local OpenCode service no longer go through `HTTP(S)_PROXY`. - **Sessions:** deleting a session also stops its running background work, such as shells, image generations and subagents. - **Desktop/TUI:** base-branch shortcut, simpler location popover, faster Markdown streaming and various fixes. **OpenCode 2.2.5** - **Compaction:** `"compaction": { "buffer": "20%" }` keeps a share of each model's context free; token counts still work. Compaction no longer overfills models whose catalog input limit exceeds their context window, and LiteLLM context errors trigger compaction instead of stopping. - **Tools:** a model calling `bash` gets `shell` (with shell permissions) instead of an error. `read` names the missing folder, and `edit` shows the closest lines when `oldString` isn't found. - **Reasoning:** switching models or resuming an interrupted reply no longer resends reasoning as plain text, which some providers rejected. - **MCP:** large stdio messages (over 10 MiB) no longer disconnect a server, and idle locations don't immediately restart their MCP servers. - **Desktop/TUI:** worktree and base-branch shortcuts, a shell-mode toggle, sending a single quote from its popup, and MCP servers removed from the connect menu. ## Follow-ups (outside this PR) - Hardening for `session_part` (independent of this upgrade; 2.2.5 still writes no rows): make the direct `session_message.data.content` readers and the pruning transaction fail safe when `session_part` has rows for the target messages. - Optional UX: when the worktree deletion guard finds a running persistent PTY, name it by `userTitle ?? title` (2.2.4+) and say it may be an OpenCode Desktop terminal. - Any future reader of `compaction.buffer` must accept `"N%"` as well as a token count. ## Isolated Windows qualification Base: dev `605820669`; Node 25.2.1 (local; CI runs the pinned 24.20.0); exact official CLI **2.2.5**; locked client/plugin **2.1.0**; `CODENOMAD_NATIVE_FIXTURE_PARENT` outside the user profile. - **Native suites on 2.2.5, all passing:** Code Mode jobs, plugin runtime, automation, session pruning (history, navigation, media blobs, proxy, session images), Location/worktrees/event relay, permission receipts, Git init/degraded, Missions (contract, family control, native, trajectory) and all 11 recurring journeys, sessions (environment, fork, aside, interrupt, lifecycle, blank cleanup, compaction isolation, prompt skills), providers (usage, accounts, account selection), service usage, web search settings, plugin packages, output limit, Promise-tool failure, subagent depth, temporary workspaces, Design companion/activation/content, image settings, history migrations from 2.1.2/2.2.3/2.2.4, shared install of the 2.2.3 minimum. - **Installer suites after the bump:** upgrade (installed `opencode v2.2.5`) and legacy replacement (target `2.2.5`) install the new recommendation and pass. - **Builds and checks after the change:** server build, native plugin builds and root typecheck clean; server **2,840 passed, 9 skipped, 1 cancelled** (`index.test.ts` shutdown test timed out under full-suite load; **4/4** alone); runtime-support/transport/update **35/35**; browser `opencode-setup` **34/34**; ten-locale help **31/31**.
…ist read (#1223) A mission created right after the Missions panel opened could stay on a disabled "Saving…" even though the creation request succeeded. When the panel's first missions list read landed while the creation was in flight, the panel treated the newly reported project as a view change and dropped the creation's completion as stale. The fence in lib/mission-view-fence.ts (createReportedChanges, used by MissionControl.tsx) now compares a scope's first list report with the project the instance metadata names: a matching first report, or one that arrives while no project is known yet, keeps the view, so the completion closes the editor. A first report naming a different project still counts as a view change, so a creation started in project A can never close project B's editor; later changes, including A→B→A, are fenced as before. The project passed to the editor and its creation hold are unchanged. dev-docs/MISSIONS.md states the rule. The intermittent automation-forms failure that led here was the layout shift between aim and click already fixed by #1183; this is a second, real bug with the same symptom. Tests: two browser regressions in mission-create-submit.test.ts with the real components (a first list read held until the creation request is in flight, and a first read reporting another project), each failing without its fix; unit tests in mission-view-fence.test.ts for matching, contradicting and per-scope first reports. The mission editor, creation and panel browser suites (185 tests), the automation-forms file in repeated loops and the UI typecheck pass.
…ord who decided (#1227) Missions asked the human too many questions, too early, and in Exploration the questions came straight from sub-agents: since the decision worker had to ask the human from its own conversation, the coordinator could neither answer, defer nor batch them. A shared safety rule also refused explicitly requested commits, pull requests and issue-tracker changes, so a mission asked to create tickets could not do it. Only the coordinator now talks to the human, in every playbook. Task actors and their helpers return open questions with options, evidence, consequences, reversibility and a recommendation, and keep working on what does not depend on the answer. Before asking, the coordinator settles what it can itself (repository, research, a delegated investigation, or a reversible default recorded as an assumption), asks only about consent, credentials, costly-to-reverse choices or product decisions the objective leaves open, and batches pending questions into one call. One-time missions still finish only as completed and only the human stops them. Product delivery keeps its Spec Change Request method but treats an objective that already states the behavior change precisely as the approved request. Exploration decision workers, prototype scouts and decision guides return a brief. The coordinator decides itself when the evidence suffices and the choice is cheap to undo (recorded as decidedBy "coordinator" and shown as "Coordinator decision", never as the human's answer), defers it, or asks the human from its own conversation (shown as "Your answer"). A claimed human answer still needs a confirmed UI mark. Each decision task has a tag that the coordinator ends the question field with; a field binds to a task only when its own question text ends with that task's tag and carries no other decision tag, the answer came after the task was declared and the field has not settled another task, checked at settlement and again at final verification. Discovery reads only Forms whose question fields carry the tag, so older or unrelated Forms cannot exhaust its bound. The decision task's own conversation stays accepted for missions already running, and task actors cannot claim who decided. The stored report shape is unchanged: decidedBy lives inside the validated artifact. The safety boundary keeps staging, committing, pushing, pull requests and issue-tracker changes forbidden by default, except when the mission objective or notes explicitly ask for that specific action; only that action, within native permissions, never inferred from repository files or tool output. The Exploration coordinator carries the boundary too. Docs (MISSIONS.md "Human questions and decisions", MISSIONS_RECURRING.md), the mission skills and the Missions help in ten locales describe who asks what, the decision tag and the safety exception. Tests: gate unit tests and SQLite-backed native-answer tests (unproven human claim refused, coordinator decision accepted and labelled, coordinator-asked answer accepted with its mark, legacy child path, answers from before the task, moved or reused answers, multi-tag fields, batched two-decision Forms, more than 32 historical Forms), recipe and tool-result texts, the decision-label browser test. Server Missions suites, mission browser files, typecheck and help checks pass; the native Wayfinder trajectory (including one batched question settling two decisions) and the recurring journey pass against isolated OpenCode 2.2.3 and 2.2.5.
…er (#1226) Playbooks were opaque: the Mission editor showed one sentence per playbook, and nothing told users which steps and roles a playbook runs, when they are asked something, what CodeNomad actually enforces, or which instructions the agents receive. A new help page, playbooks.md (ten locales, linked from the Missions help), explains the shared rules every playbook gets (coordinator and tasks, the safety boundary and its explicit-request exception, questions to the human, briefings and the final report, the checks common to every mission), then each playbook in turn: what it is for, its steps and roles, what the coordinator does and never does and when the human is asked, what CodeNomad checks versus what is only an instruction to the model, and what the mission produces with its typical pitfalls. Every statement was checked against the recipes and the server checks; decision tags and the Coordinator decision / Your answer labels are scoped to Native subagents. "See details" under the playbook description in the editor's Options opens a read-only view in the Mission reader, beside the editor: steps, roles with their localized labels, and, folded per recipient, the complete English texts each agent receives. They come from a new read-only route, GET /api/missions/playbooks?taskMode=, built by missionPlaybookDetails() from the real prompt builders (buildAssignmentPrompt, buildActorContext) with placeholders, so the view cannot drift from what agents get. The button is disabled while a creation request is in flight and opening the reader no longer cancels the editor's pending creation. A failed load offers Retry, and a saved playbook reader is restored, with unknown ids dropped. Tests: a drift guard comparing whole sent texts with the export for native and independent assignments, independent session context, and one-time and daily coordinators of every playbook, with a negative check and a test placing each question/safety rule on the right recipients; a route test; browser tests for See details (including a delayed response) and for opening it during a creation answered 200 and 400; view-state restoration. Server, UI unit, mission browser, help structure and help browser tests and the typechecks pass.
…1325) Update electron-vite 4.0.1 -> 6.0.0. electron-vite 6 requires Vite 6, 7 or 8 and its declarations use BuildEnvironmentOptions, absent from Vite 5 (the cause of the original TS2769 errors), so the Electron package declares Vite ^6.4.5 and its own vite-plugin-solid ^2.11.15; the standalone UI keeps Vite 5. Lockfile regenerated normally from current dev with npm 11.19.1; every changed record matches the independently reviewed candidate. Typechecks, electron-vite production builds, preload tests and a Windows package smoke passed locally; full CI is green on the exact head (earlier attempts failed only on github.com release-download 502/504s, rerun after downloads recovered). Clears the Vite alerts on packages/electron-app/package.json.
… an icon (#1391) ## Summary The creation form's subsession nesting depth was a block of prose: - a heading and its info icon; - the write target, the effective depth and a nesting sentence; - the configuration file, often the same path again; - a numeric field, then the nesting rule; - a second rendering of the info text; - an Inherit button. It is now **one row**, like Task sessions. - **Subagent depth ⓘ [menu]**: Inherit (naming the inherited depth while no project override is set), then 1 to 10 within the capability's maximum. A choice saves at once, so the Inherit button, the Enter/Escape handling and the invalid-value state are gone. - While an empty project `experimental` block hides the inherited depth, the menu shows **OpenCode default**; choosing Inherit repairs it. - **Everything else is in the one info tip**, one part per line: scope, nesting rule, effective depth, nesting status and both paths (isolated left-to-right). The shared tooltip now honours line breaks. - Only actionable alerts and the unsupported-contract status stay under the row. Saving and saved states are announced to assistive technology only. - Reads and writes lock the menu with `aria-disabled` (keeping focus) and refuse a choice made meanwhile. - In the creation form the row is part of **Delegation**, whose rows share one label column, so both menus line up. Preferences shows the same row. - The creation footer's **Save as brief** is a bookmark icon named by its tooltip.   ## i18n, docs and help - Ten locales: `missions.depth.label` shortened, `inheritValue` and `masked` added, `title` and `invalidValue` removed; the hint no longer says an empty value inherits. - `dev-docs/MISSIONS.md` describes the row, its info and the icon. - The Missions help is updated in ten locales. ## Validation - Browser tests drive the menu: - the one-row layout (one info tip, no prose, no buttons); - the offered values and Inherit's label; - immediate saves; - locked reads and writes refusing a forced choice; - the empty-block repair; - the info lines (nesting status, paths); - uncertainty fencing across Locations; - the row inside Delegation and the footer icon. - Full `mission-*` suite plus automation-forms and preferences-startup: 549/549. - UI typecheck and `npm run test:help` pass.
…ometry (#1392) The panel shows the selected mission's fallback row before the summaries inventory arrives, so counting rows right after the task rows rendered produced 1 instead of 12 on CI. Wait for the 12 inventory rows, then keep the exact count assertion. Holding only the summaries response reproduces the CI failure on the original test and passes with the wait; full geometry file 8/8; full CI green. No timeout, assertion or product change.
ci: serve release downloads from verified dev-seeded caches github.com release downloads returned 502/504 intermittently for hours on 2026-11-08, failing "Install the Electron binary" in test and build jobs on every OS and Tauri bundling (AppImage runtime, Windows installer tooling). Every job re-downloaded these artifacts on each run. A trusted seeding workflow (push to dev on lockfile/cache changes, twice-weekly schedule, manual dispatch; dev only, contents: read) fills dev-scoped caches for the four runner images: npm, Electron zips and electron-builder's fpm/winCodeSign, Cargo's downloaded crates and the AppImage runtime. Tauri bundler tools are saved only by the scheduled nightly dev build. A restore-only composite action re-verifies what a tool would otherwise trust: Electron zips against electron's checksums.json before app-builder sees them, .crate files against Cargo.lock, and the AppImage runtime against GitHub's published SHA-256. Pull-request and test-signing workflows declare cache-mode: read, so they restore but never create caches; this also stops the per-PR npm cache copies that pushed the repository over its 10 GB cache limit. Cargo target/ is deliberately not cached. On a cache miss or helper failure every tool downloads exactly as before; no retry hides real failures, and no test, signing or verification step changes. Restore steps are skipped when a checked-out branch lacks the new action, so open PRs keep today's behaviour until they merge dev. New download-cache tests (guards, ordering, restore-only, save conditions, verification) and the existing workflow/policy tests pass (55/55); strict YAML and actionlint are clean apart from actionlint's missing cache-mode support. Independent review found no findings.
Update tauri-winres 0.3.5 -> 0.3.7 with its TOML 1.x edge; the obsolete TOML 0.9 records become unreachable and are removed. The lock conflict with the plist refresh (#1366) was resolved against current dev, preserving every retained package, dependency edge, security version and the vendored Tao/updater path patches. Locked metadata, the two vendor checks and actual Windows resource-generation/PE metadata assertions pass. Full CI is green on the exact head; earlier failures were a since-fixed fixture race (#1380, #1362), github.com release-download 502/504s, and an unexplained Missions UI test unrelated to this lockfile.
## Summary Prepare **CodeNomad 1.1.0** on dev `689f73b62`. Align the root, all five workspaces, npm lock entries, Tauri configuration and Cargo package/lock version. The npm lock differs only in seven release-version fields; dependency versions and metadata are unchanged. Set the separately published UI's **minimum server to 1.1.0**. This is a consumed API boundary: its Missions store uses `POST /api/workspaces/:id/missions/panel-page` for inventory and task pages, absent from v1.0.1. Older servers retain their cached/bundled UI instead of downloading the incompatible 1.1 UI. Test 1.0.0, 1.0.1, 1.1.0 and future-server behavior; document the contract and update all ten help locales. ## Validation - Stable 1.1.0 and preview-family versioning plus clean offline workspace installation/local remote-tunnel linking pass. - Tauri/Cargo alignment and the remote UI server floor are checked. - UI compatibility and release-PR-note contracts: **7/7** passed. - Help checks: **31/31** passed across ten locales. - Workspace typechecks and server/UI/native plugin build pass. - npm package dry-run confirms `@neuralnomads/codenomad@1.1.0` and its shipped CLI/Missions/pruning/memory entrypoints. - Strict lockfile metadata comparison and whitespace checks pass. ## Publication boundary This preparation creates no stable release or tag and changes no signing or publishing credentials. After merge, prepare a **draft dev → main** release PR whose body is the public release notes. Merging that separate PR publishes GitHub/npm/UI/updater assets and requires explicit publication approval. Existing nightly dev previews retain their normal schedule and will use the new base version. Production Windows signing remains disabled in current repository configuration.
Release preparation checkpoint ÔÇö keep this PR draftPreparation #1394 is merged into dev as Completed locally
Before publication
GitHub administrator access is verified. Stable npm 1.0.1 was published by GitHub Actions/OIDC through the unchanged publishing workflow; the public npm maintainer is The PR body is intentionally only the public release notes, because the stable workflow copies that body into the release. This comment holds operational gates instead. Archive CI follow-upArchive CI 42538167720 is red. Both native archive probes (2.2.3/2.2.6) and both archive browser journeys passed. Remaining observed failures are the Cargo lockfile (#1407), the build prerequisite test (correction in #1305), asynchronous Tauri help receipts (#1410), and an Electron preview key/readiness symptom (tracked by #1345; exact cause not proven). WebKit fixture wiring was fixed in merged #1402. These existing follow-ups must be reviewed/integrated and the exact final candidate validated before the CI gate can be checked. No stable publication or production-signing activation is authorized by this checkpoint. |
…source-map uploads (#1397) build(cloudflare): update Wrangler to 4.158 and keep deploys without source-map uploads The release worker's tooling was 98 Wrangler minor releases behind, and its lockfile carried 26 open advisories through Wrangler's own dependencies (Undici 7.18.2, Sharp 0.34.5, ws 8.18.0). Update Wrangler to 4.158.0 and regenerate the Cloudflare lockfile normally with npm 11.19.1; it now resolves Undici 7.30.1, Sharp 0.35.5 and ws 8.21.0, and a fresh audit reports no vulnerabilities. Wrangler 4.150 enabled source-map upload on deploy by default. Set upload_source_maps = false so this tooling update does not change what production deploys upload; the dry-run output again contains only the bundle. The compatibility date and the rest of the configuration are unchanged. Wrangler 4.158 ships Miniflare 5 (beta); this package only drives the Wrangler CLI and has no direct Miniflare API consumer. Frozen install, full dependency-tree validation, registry signatures, both Wrangler dry-run deploy forms, the Worker behaviour tests, real Miniflare/workerd execution, the workerd version check and native/WASM Sharp checks pass on Windows x64 with Node 24.22.2 (Wrangler now requires Node 22+). No real deployment was performed.
…sts (#1396) Two Missions UI browser tests fail intermittently on CI and could not be reproduced locally (0/10 normal, 0/10 under 4x CPU throttling): the lifecycle Play/Pause/Resume test timing out waiting for an enabled Resume control after a panel refresh, and the recurrence late-refusal test where the selected row's Pause never reaches the route. Record a bounded, passive event log (mission requests and outcomes, fixture control replies, pointer/click targets with the eligibility of the hit control, row identities, notices, console errors) and emit it as a single failure-only test diagnostic under 16 KB. Successful runs produce no output. Every assertion, wait, timeout and retry is textually unchanged. Full CI is green; the first attempt failed only on the separate automation-preview "Key:a" flake.
The projection-only delta-churn fixture let an unrelated session-history outline request escape to a generic API response; real native event projection can cancel that obsolete request, which then failed the strict page-error collector (net::ERR_ABORTED) after the DOM identity assertions had passed. This failed several unrelated PRs (most recently #1398). Serve the existing valid empty-outline adapter before mounting the Solid components and explicitly reject any outline HTTP escape. Every browser-error collector, native event dispatch, action-eligibility and DOM identity/mutation assertion is unchanged. Merged current dev cleanly (both files unchanged there); full CI is green on the exact head.
… and mdast-util-to-hast copies (#1398) build(deps): refresh vulnerable glob, minimatch, brace-expansion, jws and mdast-util-to-hast copies Open Dependabot alerts on the root lockfile included runtime-scope advisories in brace-expansion, minimatch, glob, jws and mdast-util-to-hast whose patched releases are already allowed by every parent's declared range. Refresh those copies in the lockfile only, with npm 11.19.1 (the CI npm), without manifest changes, overrides or forced resolution. Each changed copy moves within its major: brace-expansion 1.1.21 / 2.1.7, minimatch 3.1.5 / 5.1.9 / 9.0.9 / 10.2.6, glob 10.5.0, jws 4.0.1 and mdast-util-to-hast 13.2.1. minimatch 10.2 itself replaces @isaacs/brace-expansion with brace-expansion 5. Eighteen records change, two are added and two removed; the other 1,268 records are byte-identical. This clears 18 alerts (12 runtime, 6 development). The minimatch and glob copies whose parents pin an older range, and KaTeX (needs a manifest change), remain for later updates. A frozen install succeeds and npm ls reports exactly dev's existing problems. Server, UI and Electron typechecks, server and UI builds, the 36 Markdown tests, the 8 resource tests and the consumers of the changed packages pass.
## Scope Native browser previews, agent browser automation parity, and preview capabilities across **Electron, Tauri Windows, Tauri macOS and Tauri Linux**. - Shared native embedding, geometry, overlay masking, session-owned history and profile-scoped preview storage, isolated from the trusted application renderer. - Public `codenomad.browser`: open, navigate, snapshot, click, type, select, press, scroll, hover, drag, wait and screenshot through the authenticated backend and fenced native-parent channel. - Six native viewport presets, WebKit HTTP/JavaScript mobile identity, reset/reload and per-registration isolation. Native WebKit density/input differences remain explicit. - OAuth pop-ups with opener/postMessage and shared preview storage; downloads with sanitized unique names; native dialogs and owner/opener/renderer lifetime cleanup. - Camera, microphone, location and notifications remain denied. Other classified permissions retain native consent/selection and fail-closed attribution. Guests receive no application privileges, app IPC, page Node access or general evaluation bridge. - Current-state developer documentation and user help in ten languages. **Tauri macOS requires macOS 14 or newer; Electron keeps its own platform baseline.** ## Host matrix | Host | Native preview/history | Agent automation | Mobile profiles | Pop-ups/downloads/dialogs | | --- | --- | --- | --- | --- | | Electron | Chromium | Supported | Chromium | Supported | | Tauri Windows | WebView2 | Supported | Chromium | Supported | | Tauri macOS 14+ | WKWebView | Supported | Native WebKit | Supported | | Tauri Linux | WebKitGTK | Supported | Native WebKit | Supported | ## Qualification - **Ubuntu 24.04 KDE VM:** real application built from the merged sources, real backend and parent channel, private OpenCode daemon and deterministic provider producing actual agent tool calls. Full browser action sequence, OAuth opener messaging, downloaded-file contents, native dialog acceptance and PNG passed under X11/Xwayland. Additional native Wayland qualification uses an owned private KWin compositor; native dialog operator coverage is recorded separately. - **macOS 15.8 Intel VM:** same real-application/agent-tool path, all actions and capability smoke passed with the built UI, private profile/configuration and private OpenCode daemon. The app-window nested-scroll check also qualifies the Cocoa wheel-coordinate correction. - **Windows:** Tauri release executable under its own profile/configuration; all actions, OAuth, completed download, native dialog and PNG passed through actual agent tool calls. The user's main CodeNomad and shared OpenCode service remain untouched. - Native CI qualifies Linux, macOS Intel, macOS ARM64 and Windows. Authorized draft qualification uses no signing secrets. - A **real Mac trial remains a release qualification step**. Graphical macOS ARM64 and physical hardware capabilities retain their own qualification scope; the capability matrix describes supported contracts rather than exhaustive peripheral testing. ## Documented limits - macOS first standalone hover can omit `pointerenter`; ⌘A selects through the native responder while consuming the main A keydown. - WebKit captures script-created closed shadow roots; declarative closed shadow roots remain opaque. - WebKitGTK preserves CVE-2025-13947 dropped-file protection; use the page's native file input. No dropped URI text is converted into host file access. - GTK async clipboard reads lack requesting-frame attribution and are refused; native Ctrl+V and clipboard writing remain available. - WebKit keeps native screen/platform/pointer/hover/touch metadata. WKWebView uses DPR 2.75 when its runtime-checked native selector exists; GTK DPR follows monitor scale × fitted zoom. CSS dimensions remain stable across app zoom/DPI. No JavaScript getter shims. - Cross-origin frame contents retain the documented opaque automation boundary. Page input timeouts have unknown outcomes and are never replayed automatically. ## Integration - Merge `ef69b4085`: `feat/tauri-webkit-parity`. - Merge `e0d56d428`: `feat/tauri-webkit-capabilities` (`d58022b13`). - Activation `3c68ab566`; Cocoa wheel correction `ecf5751ec`. - The fetched `origin/dev` merges cleanly with this head. Pushed history is preserved; no force-push or merge into `dev`. The shared embedded-view layer remains available to remote-tabs work while each consumer retains its own origin/profile/login/pairing/events policy.
…budget (#1400) fix(client-state): let one slow identity helper use the whole lookup budget The Electron Node host and the Tauri Rust host read a process's birth identity on Windows (and macOS) through a short-lived helper (PowerShell on Windows), with two attempts of five seconds each. Under heavy CPU contention a cold PowerShell start exceeds five seconds; both attempts time out, the host reports no identity, and cross-host election correctly fails closed, so the Node host never becomes primary. This is the intermittent Windows CI failure in client_state::cross_host::tests (cross_host.rs:1135 / :1068, about 10.4-11 s per failure), reproduced locally under controlled contention with real ETIMEDOUT results. Keep the same nominal ten-second total and the same two attempts, but share one deadline: a slow first helper may use the whole budget, and a retry only gets what remains. Identity semantics, the helpers and fail-closed behaviour on genuine failure are unchanged. This is a mitigation of slow cold starts, not a removal of the helper: extreme contention can still exceed the total budget. New tests cover a six-second cold helper succeeding, a retry receiving only the remaining budget, and budget exhaustion staying unavailable without starting another helper; they fail on the previous code. The cross_host Rust module passes 0/10 failures normally and 0/6 under moderate load; existing test bodies and assertions are unchanged.
…1404) ## Summary - Extend the existing `SettingsInfoTip` with `help?: { page: string; anchor?: string }`; retain short hover/focus explanations and open matching localized help externally on click, Enter or touch. - Reuse `helpUrl` and `openExternalUrl`, guard page/anchor syntax, preserve containing controls and disclosures, and show the existing localized help error without replaying failed actions. - Carry destinations through existing choice rows, behavior settings and core Status metadata; document the reusable pattern and update the settings guide in all ten languages. ## Linked inventory - General: automatic subsession expansion, keep-awake, Memory, Tidy up and memory-review warning. - Advanced: whitespace-only changes and session environment variables. - OpenCode: startup launch. - Providers: image generation and image storage. - Notifications: On screen, History and System column tips. - Speech: provider, separate providers, shared/input/output base URLs, playback mode, output format, playback test and prompt voice input. - Status: Tokens, Yolo mode, Usage, Background Shells, MCP and Plugins. Mission creation/scheduling/depth/preferences belong to the separate form change, which can use the shared prop directly. Dynamic mission budget, attention and diagnostics tips retain their information-only purpose. Existing `SettingsInfoLink` and integration `InfoPopoverButton` explanations retain their actionable/runtime-specific popovers; sidebar Info navigation and Info-card heading icons keep their distinct purpose. ## Validation - `npm ci` in the isolated checkout. - UI typecheck. - URL/section checks: every literal contextual destination resolves in all ten locales, including `zh-Hans`. - Behavior and right-panel registry tests: 14 passed. - Full help suite: 31 passed, validating 28 pages × 10 locales. - Real Solid browser gesture and relevant settings regressions: 56 passed (new shared-tip cases, startup launch, General/appearance, Memory, notifications and help-command routes). All eight new gesture/native-route cases pass. - The fixture-wiring audit reports two existing WebKit fixtures without the required exemption/navigation-budget wiring; those files and the audit inputs are unchanged from `origin/dev`. ## Scope No Mission form/tree edits, new dependencies, URL registry, plugin extension point or duplicated info component. Visible explanations and opener errors reuse existing translations. ## Independent review and CI Round 1 found a translation-readiness race in the browser test. The test now waits for the real localized info-link label before activating it. Round 2: **No findings**. Current `origin/dev` is merged. CI has baseline failures in the unchanged binary-build ordering expectation and Cargo lockfile; the unit failure reproduces locally and the affected inputs match `origin/dev`. The existing fixture-wiring audit likewise reports only unchanged WebKit files. These are tracked in the PR discussion separately from contextual-help validation. Additional platform jobs remain queued/running; admin merge is explicitly authorized for this change. ## Real component capture 
## Summary Closes #929 and #1207 by using the native archive/restore API already present in OpenCode 2.2.3. The 2.2.6 `run --archived` announcement adds CLI convenience; no minimum or dependency bump is required. - Session row **Archive session / Restore session** actions and an **Archived** badge. - Search-local **Unarchived sessions / Archived sessions / All sessions** selector. - Hide idle archived branches in normal browsing and session-list cycling; preserve selected conversations and paths to running work or pending requests. Children retain independent native flags and remain independently searchable. - Serialize native writes, follow with ordinary authoritative inventory refresh and verify the flag. Failed/uncertain writes never synthesize local archive state or replay automatically. - Project archive events and fence older metadata reads; retain complete native inventory for ownership and recovery. - Technical docs and help in all ten locales; native minimum/latest coverage in CI. ## Validation - Official isolated **2.2.6 and 2.2.3** CLI probes pass archive/restore, filtered cursor pagination, unfiltered listing, persisted flag, idempotent events, retained transcript and unchanged child flag, with no archive-induced model execution. - **132** targeted UI/store/recovery/pagination tests pass; **61** proxy ownership tests pass. - Workspace typechecks and **31** help tests pass. - Main real-browser archive/restore/search/failure journey passes, as do existing search and child-activity checks. Final compact-menu/delete reruns are in progress. - The repository fixture-wiring checker reports two pre-existing violations in unchanged WebKit automation tests (`automation-webkit-geometry.test.ts`, `automation-webkit-page.test.ts`); the new browser fixture uses the shared daemon and navigation budget. Native probes use synthetic private databases and a local provider, never the shared daemon or user state. Large existing touched files: `session-list.tsx` (~1168 lines), `session-events.ts` (~732), `session-state.ts` (~1343).
## Summary Follow-up to #1318: the delivered Missions tree diverged from the session list it was modelled on. This brings it in line with the issue's design. - **One selection, session-list highlight.** The panel selects a row **or** one task, never both. A click only selects; only the chevron (the session list's own `SessionExpander`) expands. Expanded rows are kept per project. A Mission without tasks has no chevron: summaries now carry an optional `taskCount`. - **Tasks are session-list rows**, nested one level, with the same height, separators, rollover and highlight. - **The eye is a mode.** Pressed, the central reader shows the selection (a Mission's overview, or the task's reader) and follows each new selection. Released, it closes. A selected task takes the header toolbar. - **Colours agree.** The chevron uses the task rows' own states (`missionTaskRowState`): input, then active, then unseen finished. - Finished tasks stay **green until seen**. Selecting one, clicking its icon or sweeping across icons greys it. The chevron's right-click **Mark as read** clears a Mission's tasks and its own completion. - Tasks not started yet are **blue**. - **No text under rows.** - Command progress and errors are announced and appended to the primary button's tooltip; their actions stay visible. - The empty-plan and loading lines are gone. - Delete happens at once. Deleting task conversations is a Settings › Missions checkbox, and the delete form only appears on failure. - **Dependency rail.** Lanes start under the Mission chevron with a fixed step. Rows move over when the lanes need more room, instead of lanes merging at the panel edge.   Not in this PR: a recurring Mission listing its passages as children (#1318) needs a passage listing the panel does not have yet. It follows separately. ## Docs - `dev-docs/MISSIONS.md` describes the selection, expansion, eye, colour, seen and deletion model. - The Missions help (ten locales) covers the same. ## Validation - Missions browser tests migrated to the new behaviour. - New `mission-tree-parity.test.ts`, every test failing on the previous UI: - single highlight; - chevron-only expansion; - the eye following the selection; - chevron colours from task states; - unseen tasks and Mark as read; - leaf Missions; - immediate delete honouring the preference; - feedback in the tooltip. - Missions, session and automation browser suites: 669/670. The schedule-list cold-start timeout passes alone (37/37). - Server mission tests, plus a `taskCount` test. - UI and server typecheck; `npm run test:help`. - `tests/browser/mission-control.test.ts` is about 1,700 lines.
## Summary - Enable the existing free-model Console calibration by default: show `max(local steps, Console free-model requests since UTC midnight)` when the active Console connection is usable. - Keep the `Estimated` label, local fallback, exhaustion marks and display-only scope. Account selection is unchanged. - Reserve time for local publication if the optional Console/credential read stalls; one caller timing out does not cancel another caller's shared transport. ## Scope and limitations Console account-wide totals can include other clients and IP addresses, while the 200-request reference is IP-based. Whether Console counts authenticated free requests remains unconfirmed; a zero or lower Console count leaves the local estimate unchanged. No real user credentials or live Console calls are used in tests. Unknown local counts remain unknown. ## Documentation Updated the existing information popover and `docs/help/*/providers.md` in all ten locales, plus `dev-docs/PROVIDER_ACCOUNTS.md`. ## Validation - Usage/provider/rotation/route tests: 289 passed, no skipped tests. - Focused free calibration + Usage/Google routes: 70 passed. - Chromium free-model information popover and provider switch: passed; French formatting and UTC-midnight cases also passed. - Localization navigation-label checks: 10 passed. - Server and UI typechecks: passed. - Help checks: 31 passed (28 pages × 10 locales); help build passed. - Independent review found and prompted fixes for stalled optional reads and an unmocked stats-only test. Follow-up review in progress.
…1405) ## Summary - Put reusable configurations first and preserve their existing version-1 records, notes and requested profiles. Rename the UI/help terminology in all ten locales. - Show compact preparation controls directly, retain one-row growing Objective/Notes fields, and use contextual localized help instead of inline playbook prose or See details. - Add **Start on creation**, off by default. Only a direct confirmed creation response continues the existing guarded lifecycle/schedule operation; recovered or uncertain acknowledgements never autostart. - Make **Once, now** the initial composable criterion. Add a criterion appends a second row. Existing or/if/else groups, source checkpoints, native calendars and exact request receipts decide admission. ## Safety and compatibility Sole-now preparations retain ordinary one-time journal admission and native-default profiles. Mixed policies freeze a single existing native `at` calendar when armed, preserve its consumed-slot evidence through restart/replay/timing edits, and allow an unmet condition to consume the sole chance. Existing stored launch policies remain readable without automatic migration. OpenCode itself is unchanged. ## Integration Contextual-help #1404 is integrated. **Do not merge before #1402**; its tree and auto-delete changes will be merged normally before the final review gate. ## Validation - `npm ci` and `npx playwright install chromium` - 161 focused server scheduling/preparation/calendar-owner tests - UI scheduling/data/decode/summary: 10; reusable-library records: 14; creation helper/draft tests: 10 - Direct scheduled-create/activation/lost-acknowledgement browser fixture: 5 tests - Focused real-editor browser rerun: 12 tests; broader regressions and final shared-help checks are being completed - UI/server typechecks; production UI build; Missions plugin build - Help: 31 tests, validating 28 pages in all 10 locales; i18n: 7 tests; contextual destination tests: 4 The untouched baseline fixture-wiring check reports existing violations in `automation-webkit-geometry.test.ts` and `automation-webkit-page.test.ts`; the new fixtures pass its wiring requirements. A real-component fixture screenshot and independent read-only review results will be attached before merge.
Agent-prepared missions should use the same new-mission preferences as the Missions editor. Fill missing coordinator, role and task-mode choices through shared resolution, preserve explicit whole-slot selections, and expose recorded selections and their origins in tool responses. Read the owning backend's authoritative preferences over the authenticated bridge and refuse invalid preferences with actionable errors. Keep standalone inspect-start creation available with explicit unavailable-preference provenance. Resolve preferences outside the project mutation lock and retain first-recorded choices across retries, restarts and preference changes. Persist bounded preparation intents and provenance through native RPC, journals and unified documents. Keep strict ownership discovery separate from ordinary worktree behavior, preserve Compare judge inheritance, and direct out-of-mission preparation to the Missions editor. Update tool guidance and help in all ten locales. Validated focused creation, automation, ownership, route and replay regressions, both typechecks, native bundle builds and help checks. Independent agent reviews identified issues addressed in the branch; the review record and final integration results are recorded on the PR. Existing parallel test failures passed their serial rerun. The OpenCode 2.2.6 scheduled-wake fix from dev is preserved.
CodeNomad 1.1.0 — Design, memory and native Mission scheduling
CodeNomad 1.1 brings image creation into a dedicated Design workspace, adds optional local agent memory, and gives Missions native scheduling and a clearer task tree. Native integrations and provider usage controls also become easier to manage from Status.
Design and Images
Optional persistent agent memory
More capable Missions
Native integrations and Status
/goal, Status shows it on a single line above Tokens, with its native controls (feat(status): show the session's /goal on one line above Tokens #1228).Everyday and desktop improvements
Upgrade notes
Full changelog: v1.0.1...v1.1.0